// JS функции

// браузърът зарежда първо тези (стандартните) функции, от което следва, че могат да бъдат изпълнени преди декларацията им
function functionName () 
{
	// code
}

// тези (анонимни) функции могат да бъдат изпълнени след като браузърът е изпълнил декларацията им
var varName = function() {
	console.log('Hello');
};

// присвояване на функция на променлива, при което при всяко извикване на променливата се изпълва кодът във функцията, а стойността на променливата е резултатът от return-а на функцията
var varName = function functionName()
{
	console.log('Hello');
};

// инициализация на функция и изпълнението ѝ на момента
(function functionName()
{
	// code
})();

// като параметър на функция може да се подаде функция
functionName(5, 3, someFunctionName);
functionName(5, 3, function() { /* code */ });

// можем да използваме изрази за параметри на функциите
functionName(2 + 3);

// най-ефективният начин за деклариране на for цикъл
for (var i = 0, len = arr.length; i < len; i++)
{
	// code
}

// замерване на времето за изпълнения на функция, като включва и времето на breakpoint
console.time('functionName');
functionName();
console.timeEnd('functionName');


function fN(a, b, c)
{
	console.log(arguments);
	var a = arguments[0]; // ще прихванем първия периметър подаден при извикването на функцията
}
fN(3, 5, 8); // ще върне всички параметри на функцията

// arguments. -> дава доста възможности (с точка)

// всяка функция връща undefined по принцип, ако няма зададен return

// променливата се превръща във функция
function sampleFunctionName()
{
	return anotherSampleFunctionName; // без () на функцията, иначе ще се изпълни "anotherSampleFunctionName()"!
}
function anotherSampleFunctionName()
{
	// code
}
var a = sampleFunctionNameOne();
a(); // ще се изпълни "// code"

// return; === return undefined;

// проверка дали 'а' съществува в даден масив
function fN(a)
{
	var arr = [1, 2, 3];

	if(arr.indexOf(a) > -1)
	{
		return true;
	}
	else
	{
		return false;
	}
}

// ако използваме функция за проверка, дали нещо е вярно се връща true или false; ако функцията е за намирането на елемент или индексът му, в случай, че не е намерен е препоръчително функцията да връща null

// function scope - всичко в дадена функция е недостъпно извън нея (важи само за функциите, всички останали конструкции нямат собствен scope), освен глобалните променливи, които независимо къде са декларирани, са достъпни отвсякъде

// всяка променлива декларирана извън функция приспада към глобалния scope, което е непрепоръчително да се прави

// добра практика е целият файл да е заграден от функция от типа "(function(){ })();", за да е сигурно, че променливите от файла няма да са достъпни извън него

// всеки refresh на страницата презарежда всички скриптове

// резултатът на конзолата от предстоящия код е: "undefined, 8, 5", защото браузърите след функциите зареждат и всички променливи, и съобразяват, дали нямат по-конкретен scope от вътрешна функция
var sampleVar = 5;
function sampleFunctionName() {
	console.log(sampleVar);
	var sampleVar = 8;
	console.log(sampleVar);
};
sampleFunctionName();
console.log(sampleVar);

// ще се изпълни втората функция с параметри sampleValue и undefined
function sampleFuncName(sampleVar) {
	// code
}
function sampleFuncName(sampleVar, anotherSampleVar) {
	// another code
}
sampleFuncName(sampleValue);

// можем да изпълним функция с непълния ѝ брой параметри, на която всички параметри, въпреки това, ще са достъпни чрез "arguments"

// добър начин за реализирането на една функция с различен на брой параметри е да се проверява arguments.length в switch и за всеки case да се извиква желаната функция спрямо броя на параметрите

// добра практика е всички променливи в даден scope да се декларират с една "var" инициализация, изредени със запетайки

// начинът за инициализиране на параметри с default-на стойност е във функцията да се декларират параметрите по следния начин: sampleParam = sampleParam || defaultValue(по наше усмотрение)